﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using EzPos.Model.Common;
using EzPos.Model.Product;
using EzPos.Properties;
using EzPos.Service;
using EzPos.Service.Common;
using EzPos.Service.Product;
using EzPos.Service.User;

namespace EzPos.GUIs.Forms
{
    public partial class FrmProduct : Form
    {
        private CommonService _commonService;
        private bool _isFromSale;
        private bool _isModified;
        private Product _product;
        private ProductService _productService;
        private BindingList<Product> _productList;
        private float _exchangeRate;

        public FrmProduct()
        {
            InitializeComponent();
        }

        public CommonService CommonService
        {
            set { _commonService = value; }
        }

        public ProductService ProductService
        {
            set { _productService = value; }
        }

        public Product Product
        {
            get { return _product; }
            set { _product = value; }
        }

        public bool IsFromSale
        {
            get { return _isFromSale; }
            set { _isFromSale = value; }
        }

        private void SetModifydStatus(bool modifyStatus)
        {
            _isModified = modifyStatus;
            btnSave.Enabled = modifyStatus;
        }

        private void FrmProductAdvance_FormClosing(object sender, FormClosingEventArgs e)
        {
            if ((DialogResult == DialogResult.Cancel) && (_isModified))
            {
                const string briefMsg = "អំពីការបោះបង់";
                var detailMsg = Resources.MsgOperationRequestCancel;
                using (var frmMessageBox = new FrmExtendedMessageBox())
                {
                    frmMessageBox.BriefMsgStr = briefMsg;
                    frmMessageBox.DetailMsgStr = detailMsg;
                    if (frmMessageBox.ShowDialog(this) != DialogResult.OK)
                    {
                        e.Cancel = true;
                        return;
                    }
                }
            }

            if (_isModified) 
                return;

            DialogResult = DialogResult.Cancel;
        }

        private void ModificationHandler(object sender, EventArgs e)
        {            
            GenerateProductCode();
            SetModifydStatus(true);

            if(sender == null)
                return;

            if(!sender.GetType().Equals(typeof(TextBox)))
                return;

            var txtSource = sender as TextBox;
            if (txtSource == null)
                return;

            switch (txtSource.Name)
            {
                case "txtUPInRiel":
                    SetUnitPrice(txtSource, txtUPInDollar, txtSource.Text, true);
                    break;
                case "txtUPInDollar":
                    SetUnitPrice(txtSource, txtUPInRiel, txtSource.Text, false);
                    break;
                case "txtUPOutRiel":
                    SetUnitPrice(txtSource, txtUPOutDollar, txtSource.Text, true);
                    break;
                case "txtUPOutDollar":
                    SetUnitPrice(txtSource, txtUPOutRiel, txtSource.Text, false);
                    break;
            }
        }

        private void CmbCategoryEnter(object sender, EventArgs e)
        {
            cmbCategory.SelectedIndexChanged += ModificationHandler;
            cmbCategory.TextChanged += ModificationHandler;
        }

        private void TxtUpInEnter(object sender, EventArgs e)
        {
            txtUPInRiel.TextChanged += ModificationHandler;
        }

        private void TxtUpOutEnter(object sender, EventArgs e)
        {
            txtUPOutRiel.TextChanged += ModificationHandler;
        }

        private void TxtPhotoPathTextChanged(object sender, EventArgs e)
        {
            ModificationHandler(sender, e);
        }

        private void CmbCategoryLeave(object sender, EventArgs e)
        {
            cmbCategory.SelectedIndexChanged -= ModificationHandler;
            cmbCategory.TextChanged -= ModificationHandler;
        }

        private void TxtUpInLeave(object sender, EventArgs e)
        {
            txtUPInRiel.TextChanged -= ModificationHandler;
            try
            {
                txtUPInRiel.Text = float.Parse(txtUPInRiel.Text).ToString("N", AppContext.CultureInfo);
            }
            catch (Exception exception)
            {
                FrmExtendedMessageBox.UnknownErrorMessage(
                    Resources.MsgCaptionUnknownError,
                    exception.Message);
            }
        }

        private void TxtUpOutLeave(object sender, EventArgs e)
        {
            if (txtUPOutRiel.Text.Length == 0)
                txtUPOutRiel.Text = Resources.ConstAmountZero;

            txtUPOutRiel.TextChanged -= ModificationHandler;
        }

        private void FrmProduct_Load(object sender, EventArgs e)
        {
            if (_productService == null)
                _productService = ServiceFactory.GenerateServiceInstance().GenerateProductService();

            if (_commonService == null)
                _commonService = ServiceFactory.GenerateServiceInstance().GenerateCommonService();

            //Retrieve exchange rate
            _exchangeRate = AppContext.ExchangeRate.ExchangeValue;

            if (!UserService.AllowToPerform(Resources.PermissionViewAllProductInfo))
                txtUPInRiel.Visible = false;

            var searchCriteria = 
                new List<string>
                {
                    "ParameterTypeId IN (" +
                    Resources.AppParamProductCodeLength + ", " +
                    Resources.AppParamCategory + ", " +
                    Resources.AppParamMark + ", " +
                    Resources.AppParamColor + ", " +
                    Resources.AppParamSize + ")"
                };
            var objectList = _commonService.GetAppParameters(searchCriteria);
            var productCodeLengthList = 
                _commonService.GetAppParametersByType(
                    objectList, 
                    Int32.Parse(Resources.AppParamProductCodeLength));
            if (productCodeLengthList.Count != 0)
            {
                var productCodeLength = productCodeLengthList[0] as AppParameter;
                if (productCodeLength != null)
                {
                    int codeLength;
                    Int32.TryParse(
                        (string.IsNullOrEmpty(productCodeLength.ParameterLabel) ?
                        string.Empty :
                        productCodeLength.ParameterLabel),
                        out codeLength);
                }
            }

            _commonService.PopAppParamExtendedCombobox(
                ref cmbCategory, objectList, int.Parse(Resources.AppParamCategory), true);

            _productList = new BindingList<Product>();
            cmbProduct.DataSource = _productList;
            cmbProduct.DisplayMember = Product.ConstForeignCode;
            cmbProduct.ValueMember = Product.ConstProductId;
            cmbProduct.SelectedIndex = -1;

            SetProductInfo(_product);

            txtPhotoPath.TextChanged += TxtPhotoPathTextChanged;

        }

        private void SetProductInfo(Product product)
        {
            if (product == null)
                return;

            lblProductName.Text = string.Format("{0}{1}{2}", product.ProductName, "\r", product.ProductCode);
            cmbCategory.SelectedValue = product.CategoryId;
            txtForeignCode.Text = product.ForeignCode;
            txtDescription.Text = product.Description;
            txtQtyPrmotion.Text = product.QtyPromotion.ToString("N0");
            txtQtyBonus.Text = product.QtyBonus.ToString("N0");
            
            SetUnitPrice(
                txtUPInRiel,
                txtUPInDollar,
                product.UnitPriceIn.ToString("N", AppContext.CultureInfo), 
                true);

            SetUnitPrice(
                txtUPOutRiel,
                txtUPOutDollar,
                product.UnitPriceOut.ToString("N", AppContext.CultureInfo),
                true);
            
            txtPhotoPath.Text = product.PhotoPath;
            if (product.PhotoPath == null)
                ptbProduct.Image = Resources.NoImage;
            else
                ptbProduct.ImageLocation = product.PhotoPath;
        }

        public void GenerateProductCode()
        {
            if (cmbCategory.SelectedItem == null)
                return;

            lblProductName.Text = cmbCategory.Text;

            if (_product == null) 
                return;

            if (!String.IsNullOrEmpty(_product.ProductCode))
                lblProductName.Text += string.Format("{0}{1}", "\r", _product.ProductCode);
        }

        private void BtnSaveClick(object sender, EventArgs e)
        {
            try
            {
                if ((cmbCategory.SelectedIndex == -1)
                    || (string.IsNullOrEmpty(txtDescription.Text))
                    || (string.IsNullOrEmpty(txtForeignCode.Text)))
                {
                    const string briefMsg = "អំពីពត៌មាន";
                    var detailMsg = Resources.MsgInvalidData;
                    using (var frmMessageBox = new FrmExtendedMessageBox())
                    {
                        frmMessageBox.BriefMsgStr = briefMsg;
                        frmMessageBox.DetailMsgStr = detailMsg;
                        frmMessageBox.IsCanceledOnly = true;
                        frmMessageBox.ShowDialog(this);
                        return;
                    }
                }

                if (_product == null)
                    _product = new Product();

                _product.CategoryId = int.Parse(cmbCategory.SelectedValue.ToString());
                _product.CategoryStr = cmbCategory.Text;
                _product.ProductName = _product.CategoryStr;
                _product.UnitPriceIn = float.Parse(txtUPInRiel.Text);
                _product.UnitPriceOut = float.Parse(txtUPOutRiel.Text);
                _product.Description = txtDescription.Text;
                _product.ForeignCode = txtForeignCode.Text;
                _product.QtyPromotion = float.Parse(txtQtyPrmotion.Text);
                _product.QtyBonus = float.Parse(txtQtyBonus.Text);

                if (txtPhotoPath.Text.Length == 0)
                {
                    _product.PhotoPath = _product.PhotoPath;
                    _product.ProductPic = Resources.NoImage;
                }
                else
                {
                    var fileInfo = new FileInfo(txtPhotoPath.Text);
                    if (fileInfo.Exists)
                    {
                        _product.PhotoPath = txtPhotoPath.Text;
                        _product.ProductPic = Image.FromFile(_product.PhotoPath);
                    }
                    else
                        _product.ProductPic = Resources.NoImage;
                }

                if (_productService == null)
                    _productService = ServiceFactory.GenerateServiceInstance().GenerateProductService();

                _product.DisplayName = _product.ProductName + "\r" +
                                       "Size: " + _product.SizeStr + "\r" +
                                       "Code: " + _product.ProductCode;
                if (!string.IsNullOrEmpty(_product.ForeignCode))
                    _product.DisplayName += " (" + _product.ForeignCode + ")";

                if (!_isFromSale)
                {
                    _productService.ManageProduct(
                        _product,
                        _product.ProductId != 0 ? Resources.OperationRequestUpdate : Resources.OperationRequestInsert);
                }

                DialogResult = DialogResult.OK;
            }
            catch (Exception exception)
            {
                FrmExtendedMessageBox.UnknownErrorMessage(
                    Resources.MsgCaptionUnknownError,
                    exception.Message);
            }
        }

        private void PtbProductMouseClick(object sender, MouseEventArgs e)
        {
            if (_isFromSale)
                return;

            if (e == null)
                return;

            switch (e.Button)
            {
                case MouseButtons.Left:
                    ImportIndividualCatalog();
                    break;
                case MouseButtons.Right:
                    if (_product == null)
                        cmsCatalog.Show(ptbProduct, e.X, e.Y);
                    break;
            }
        }

        private void ImportIndividualCatalog()
        {
            using (var openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = Resources.ConstExtensionImage;
                openFileDialog.Multiselect = false;
                if (openFileDialog.ShowDialog() != DialogResult.OK) 
                    return;

                ptbProduct.ImageLocation = openFileDialog.FileName;
                txtPhotoPath.Text = openFileDialog.FileName;
            }
        }

        private void ImportAllCatalogs()
        {
            using (var folderBrowserDialog = new FolderBrowserDialog())
            {
                folderBrowserDialog.ShowNewFolderButton = false;
                if (folderBrowserDialog.ShowDialog() != DialogResult.OK) 
                    return;

                const string briefMsg = "អំពីការលុប";
                var detailMsg = Resources.MsgOperationImportGroupCatalog;
                using (var frmMessageBox = new FrmExtendedMessageBox())
                {
                    frmMessageBox.BriefMsgStr = briefMsg;
                    frmMessageBox.DetailMsgStr = detailMsg;
                    if (frmMessageBox.ShowDialog(this) != DialogResult.OK)
                        return;
                }

                if (_productService == null)
                    _productService = ServiceFactory.GenerateServiceInstance().GenerateProductService();

                _productService.ImportGroupCatalog(
                    folderBrowserDialog.SelectedPath,
                    Int32.Parse(cmbCategory.SelectedValue.ToString()),
                    cmbCategory.Text,
                    0,
                    string.Empty,
                    0,
                    string.Empty,
                    0,
                    string.Empty);

                _isModified = true;
                DialogResult = DialogResult.OK;
            }
        }

        private void TsmIndividualClick(object sender, EventArgs e)
        {
            ImportIndividualCatalog();
        }

        private void TsmAllClick(object sender, EventArgs e)
        {
            ImportAllCatalogs();
        }

        private void TmsGroupClick(object sender, EventArgs e)
        {
            using (var openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = Resources.ConstExtensionImage;
                openFileDialog.Multiselect = true;
                if (openFileDialog.ShowDialog() != DialogResult.OK) 
                    return;

                if (openFileDialog.FileNames.Length == 0)
                    return;

                const string briefMsg = "អំពីការបង្កើតផលិតផល";
                var detailMsg = Resources.MsgOperationImportGroupCatalog;
                using (var frmMessageBox = new FrmExtendedMessageBox())
                {
                    frmMessageBox.BriefMsgStr = briefMsg;
                    frmMessageBox.DetailMsgStr = detailMsg;
                    if (frmMessageBox.ShowDialog(this) != DialogResult.OK)
                        return;
                }

                if (_productService == null)
                    _productService = ServiceFactory.GenerateServiceInstance().GenerateProductService();

                _productService.ImportGroupCatalog(
                    openFileDialog.FileNames,
                    Int32.Parse(cmbCategory.SelectedValue.ToString()),
                    cmbCategory.Text,
                    0,
                    string.Empty,
                    0,
                    string.Empty,
                    0,
                    string.Empty);

                _isModified = true;
                DialogResult = DialogResult.OK;
            }
        }

        private void TsmImportClick(object sender, EventArgs e)
        {
            if (!UserService.AllowToPerform(Resources.PermissionImportExportProduct))
            {
                const string briefMsg = "អំពី​សិទ្ឋិ​ប្រើ​ប្រាស់";
                var detailMsg = Resources.MsgUserPermissionDeny;
                using (var frmMessageBox = new FrmExtendedMessageBox())
                {
                    frmMessageBox.BriefMsgStr = briefMsg;
                    frmMessageBox.DetailMsgStr = detailMsg;
                    frmMessageBox.IsCanceledOnly = true;
                    frmMessageBox.ShowDialog(this);
                    return;
                }
            }

            using (var folderBrowserDialog = new FolderBrowserDialog())
            {
                folderBrowserDialog.ShowNewFolderButton = false;
                if (folderBrowserDialog.ShowDialog() != DialogResult.OK) 
                    return;

                const string briefMsg = "អំពីការលុប";
                var detailMsg = Resources.MsgOperationImportGroupCatalog;
                using (var frmMessageBox = new FrmExtendedMessageBox())
                {
                    frmMessageBox.BriefMsgStr = briefMsg;
                    frmMessageBox.DetailMsgStr = detailMsg;
                    if (frmMessageBox.ShowDialog(this) != DialogResult.OK)
                        return;
                }

                if (_productService == null)
                    _productService = ServiceFactory.GenerateServiceInstance().GenerateProductService();

                _productService.ImportProductFromXml(
                    folderBrowserDialog.SelectedPath,
                    "ProductList.xml");

                _isModified = true;
                DialogResult = DialogResult.OK;
            }
        }

        //private void TxtProductCodeLeave(object sender, EventArgs e)
        //{
        //    txtForeignCode.TextChanged -= ModificationHandler;
        //    string detailMsg;
        //    if (!_productService.IsValidatedProductCode(txtForeignCode.Text, out detailMsg))
        //    {
        //        const string briefMsg = "អំពីពត៌មាន";
        //        using (var frmMessageBox = new FrmExtendedMessageBox())
        //        {
        //            frmMessageBox.BriefMsgStr = briefMsg;
        //            frmMessageBox.DetailMsgStr = detailMsg;
        //            frmMessageBox.IsCanceledOnly = true;
        //            return;
        //        }
        //    }
        //    DoProductFetching(txtForeignCode.Text, true);
        //}

        private void CmbProductSelectedIndexChanged(object sender, EventArgs e)
        {
            if ((String.IsNullOrEmpty(cmbProduct.DisplayMember)) ||
                (String.IsNullOrEmpty(cmbProduct.ValueMember)) ||
                (cmbProduct.SelectedIndex == -1))
                return;

            try
            {
                var product = (Product)cmbProduct.SelectedItem;
                if (product == null)
                    return;

                const string briefMsg = "អំពីពត៌មាន";
                var detailMsg = Resources.MsgConfirmEditExistingProduct;
                using (var frmMessageBox = new FrmExtendedMessageBox())
                {
                    frmMessageBox.BriefMsgStr = briefMsg;
                    frmMessageBox.DetailMsgStr = detailMsg;
                    if (frmMessageBox.ShowDialog(this) != DialogResult.OK)
                    {
                        return;
                    }
                }

                _product = product;
                SetProductInfo(_product);
            }
            catch (Exception exception)
            {
                FrmExtendedMessageBox.UnknownErrorMessage(
                    Resources.MsgCaptionUnknownError,
                    exception.Message);
            }
        }

        //private void DoProductFetching(string foreignCode, bool isAllowed)
        //{
        //    if (String.IsNullOrEmpty(foreignCode))
        //        return;

        //    foreignCode = foreignCode.Replace("+", string.Empty);
        //    foreignCode = foreignCode.Replace("-", string.Empty);
        //    cmbProduct.SelectedIndex = -1;
        //    var selectedIndex = cmbProduct.FindStringExact(foreignCode);
        //    cmbProduct.SelectedIndex = selectedIndex;
        //    if ((selectedIndex != -1) || (!isAllowed)) 
        //        return;

        //    var strCriteria = 
        //        new List<string>
        //        {
        //            "ForeignCode|" + foreignCode,
        //            "QtyInStock > 0",
        //            "ProductId <> " + (_product == null ? 0 : _product.ProductId)
        //        };
        //    var productList = _productService.GetObjects(strCriteria);
        //    if (productList.Count == 0) 
        //        return;

        //    foreach (Product product in productList)
        //        _productList.Add(product);

        //    DoProductFetching(foreignCode, false);
        //}

        private void TxtDescriptionEnter(object sender, EventArgs e)
        {
            try
            {
                InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new System.Globalization.CultureInfo("km-KH"));
            }
            catch (Exception)
            {
                try
                {
                    InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new System.Globalization.CultureInfo("ca"));
                }
                catch (Exception)
                {
                    InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new System.Globalization.CultureInfo("en"));
                }
            }

            txtDescription.TextChanged += ModificationHandler;
        }

        private void TxtDescriptionLeave(object sender, EventArgs e)
        {
            InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new System.Globalization.CultureInfo("en"));
            txtDescription.TextChanged -= ModificationHandler;
        }

        private void SetUnitPrice(Control txtSource, Control txtDestination, string txtAmount, bool isLocalCurrency)
        {
            float amount;
            float.TryParse(txtAmount, out amount);

            if (isLocalCurrency)
            {
                txtSource.Text = txtAmount;
                txtDestination.Text = (amount/_exchangeRate).ToString("N", AppContext.CultureInfo);
            }
            else
            {
                txtSource.Text = txtAmount;
                txtDestination.Text = (amount * _exchangeRate).ToString("N", AppContext.CultureInfo);
            }
        }

        private void TxtUpInDollarEnter(object sender, EventArgs e)
        {
            txtUPInDollar.TextChanged += ModificationHandler;
        }

        private void TxtUpInDollarLeave(object sender, EventArgs e)
        {
            txtUPInDollar.TextChanged -= ModificationHandler;
        }

        private void TxtUpOutDollarEnter(object sender, EventArgs e)
        {
            txtUPOutDollar.TextChanged += ModificationHandler;
        }

        private void TxtUpOutDollarLeave(object sender, EventArgs e)
        {
            txtUPOutDollar.TextChanged -= ModificationHandler;
        }

        private void TxtForeignCodeEnter(object sender, EventArgs e)
        {
            txtForeignCode.TextChanged += ModificationHandler;
        }

        private void TxtForeignCodeLeave(object sender, EventArgs e)
        {
            txtForeignCode.TextChanged -= ModificationHandler;
        }

        private void TxtPrmotionQtyEnter(object sender, EventArgs e)
        {
            txtQtyPrmotion.TextChanged += ModificationHandler;
        }

        private void TxtPrmotionQtyLeave(object sender, EventArgs e)
        {
            txtQtyPrmotion.TextChanged -= ModificationHandler;
        }

        private void TxtQtyBonusEnter(object sender, EventArgs e)
        {
            txtQtyBonus.TextChanged += ModificationHandler;
        }

        private void TxtQtyBonusLeave(object sender, EventArgs e)
        {
            txtQtyBonus.TextChanged -= ModificationHandler;
        }
    }
}